<?php
include (dirname(__FILE__) .DIRECTORY_SEPARATOR.'gol_class.php');
class Game_Of_Life {
    public $golOb;
	public $window;    
    public $envFilePath;    
    public $W=array();
	public $ENV = array();   
    public $q = false;
    public $stop = true;
	protected $pixmap = null;
    public function __construct() {
        $this->loadEnv();
        $this->golOb = new Game_Of_Life_Engine($this->ENV['bw'], $this->ENV['bh'], $this);
        $this->loadGlade();
        $this->setCallBacks();
        $this->mainLoop();
    }
    private function mainLoop() {
        while (!$this->stop && !$this->q) {            
            while (Gtk::events_pending()) {Gtk::main_iteration();}
            $this->golOb->turn();	
        }
        if (!$this->stop) {gtk::main_quit();}
    }
    private function loadGlade() {
        $this->W['gade'] = new GladeXML(dirname(__FILE__) ."/gld/main.glade");
        $this->window = $this->W['gade']->get_widget("golWin");
        $this->W['board'] = $this->W['gade']->get_widget("board");
        $this->W['start'] = $this->W['gade']->get_widget("start");
        $this->W['stop'] = $this->W['gade']->get_widget("stop");
        $this->W['clear'] = $this->W['gade']->get_widget("clear");
        $this->W['board']->set_size_request($this->ENV['bw']*$this->ENV['pSize'], $this->ENV['bh']*$this->ENV['pSize']);
    }
    private function setCallBacks() {
        $this->window->connect('destroy', array($this, 'close'));
        $this->W['board']->connect('configure_event', array($this, 'configureEvent'));
        $this->W['board']->connect('expose_event', array($this, 'exposeEvent'));
        $this->W['board']->connect('motion_notify_event', array($this, 'motionNotifyEvent'));
        $this->W['board']->connect('button_press_event', array($this, 'buttonPressEvent'));
        $this->W['start']->connect('clicked', array($this, 'start'));
        $this->W['clear']->connect('clicked', array($this, 'clear'));
        $this->W['stop']->connect('clicked', array($this, 'stop'));
    }
    function clear() {
        $this->stop();
        $this->golOb = new Game_Of_Life_Engine($this->ENV['bw'], $this->ENV['bh'], $this);
        $tmp = $this->ENV['pSize'];
        $this->ENV['pSize'] = $this->ENV['pSize']*$this->ENV['bw'];
        $this->setPix($this->W['board'], 0, 0, false);
        $this->ENV['pSize'] = $tmp;
    }
    function start() {
        if ($this->stop) {
            $this->stop = false;
            $this->mainLoop();
        }
    }
    function stop() {
        $this->stop = true;
    }
    function configureEvent($widget, $event) {
        $this->pixmap = new GdkPixmap($widget->window, $widget->allocation->width, $widget->allocation->height, -1);
        $this->pixmap->draw_rectangle($widget->style->white_gc, true, 0, 0, $widget->allocation->width, $widget->allocation->height);
        return true;
    }
    function exposeEvent($widget, $event) {
        if ($this->pixmap != null) {
            $widget->window->draw_drawable($widget->style->fg_gc[$widget->state], $this->pixmap, $event->area->x, $event->area->y, $event->area->x, $event->area->y, $event->area->width, $event->area->height);
            return false;
        }
    }
    function buttonPressEvent($widget, $event) {
        if ($event->button == 1 && $this->pixmap) {
            $this->drawPix($widget, (int)$event->x, (int)$event->y);
        }
        return true;
    }
    function motionNotifyEvent($widget, $event) {
        $window = $event->window;
        $pointer = $window->get_pointer();
        $x = $pointer[0];
        $y = $pointer[1];
        $state = $pointer[2];
        if (($state&Gdk::BUTTON1_MASK) && $this->pixmap) {
            $this->drawPix($widget, $x, $y);
        }
        return true;
    }
    function drawPix($widget, $x, $y) {
        $x = ceil(intval($x-4) /$this->ENV['pSize']) *$this->ENV['pSize'];
        $y = ceil(intval($y-4) /$this->ENV['pSize']) *$this->ENV['pSize'];
        $this->golOb->board[$x/$this->ENV['pSize']][$y/$this->ENV['pSize']] = true;
        $this->pixmap->draw_rectangle($widget->style->black_gc, true, $x, $y, $this->ENV['pSize'], $this->ENV['pSize']);
        $widget->queue_draw_area($x, $y, $this->ENV['pSize'], $this->ENV['pSize']);
    }
    function setPix($widget, $x, $y, $black = true) {
        $x = (ceil(intval($x) /$this->ENV['pSize']) *$this->ENV['pSize']);
        $y = (ceil(intval($y) /$this->ENV['pSize']) *$this->ENV['pSize']);
        if (!$black) {
            $this->pixmap->draw_rectangle($widget->style->white_gc, true, $x, $y, $this->ENV['pSize'], $this->ENV['pSize']);
        } else {
            $this->pixmap->draw_rectangle($widget->style->black_gc, true, $x, $y, $this->ENV['pSize'], $this->ENV['pSize']);
        }
        $widget->queue_draw_area($x, $y, $this->ENV['pSize'], $this->ENV['pSize']);
    }
    private function loadEnv() {
        $this->envFilePath = dirname(__FILE__) .DIRECTORY_SEPARATOR.'data/env';
        if (is_file($this->envFilePath)) {
            $this->ENV = unserialize(file_get_contents($this->envFilePath));
        } else {
            $this->ENV['bw'] = 80;
            $this->ENV['bh'] = 80;
            $this->ENV['pSize'] = 6;            
        }
    }
    private function saveEnv() {
        $data = serialize($this->ENV);
        file_put_contents($this->envFilePath, $data);
    }
    function close() {
        $this->saveEnv();
        $this->q = true;
		if ($this->stop) {
            gtk::main_quit();
        }
    }
}
?>